﻿using Dark_Core_Library.NetworkModules.HTTP;
using Dark_Core_Library.UniModules.Models;
using DetectWebApi.Models.User;
using DetectWebApi.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.VisualBasic;
using MongoDB.Bson;
using Serilog;
using static MongoDB.Driver.WriteConcern;

namespace DetectWebApi.Controllers
{
    [ApiController]
    [Route("[controller]:[action]")]
    public class UserController : Controller
    {
        private readonly UserService Service;

        public UserController(UserService service)
        {
            this.Service = service;
        }


        #region Craete

        [HttpPost]
        public async Task<ActionResult> Create(UniHttpRequest request)
        {
            var containsResult = request.Contains("username", "password");
            if(!containsResult.IsSuccess) return Ok(containsResult.ToUniHttpResponse());
            if (request.args == null) return Ok("No args provided".ToUniHttpResponse("Error",0));
            var usernameGetResult = request.TryGetValue("username", out string username,"ERROR");
            var passwordGetResult = request.TryGetValue("password", out string password, "ERROR");
            if (!usernameGetResult.IsSuccess) return Ok(usernameGetResult.ToUniHttpResponse());
            if (!passwordGetResult.IsSuccess) return Ok(passwordGetResult.ToUniHttpResponse());
            /*
             * 检测重复用户名
             */
            var pagingParam = request.ExtractPagingParams(valueFieldName:"username");
            var aggregation = new object().CreateOperationModeAggregation("Username".ToUserQueryMode(), pagingParam);
            var queryResult = await Service.GetUserListAsync(aggregation);
            if (queryResult.Result.Length > 0) return Ok("Username already exists".ToUniHttpResponse("Error", 0));
            /*
             * 返回数据
             */
            SUserDocument sUser = new(User:username, Pass: password);
            var insertResult = await Service.InsertUserAsync(sUser);
            return Ok(insertResult.ToUniHttpResponse());
        }


        #endregion

        #region Query


        //TODO:后续设为超管权限
        [HttpPost]
        [Authorize(Roles = "999")]
        public async Task<ActionResult> Query(UniHttpRequest request)
        {
            var containsResult = request.Contains("value","mode");
            if (!containsResult.IsSuccess) return Ok(containsResult.ToUniHttpResponse());
            request.TryGetValue("mode", out string mode, "ERROR");
            var pagingParam = request.ExtractPagingParams();
            var aggregation = new object().CreateOperationModeAggregation(mode.ToUserQueryMode(), pagingParam);
            var queryResult = await Service.GetUserListAsync(aggregation);
            var countResult = await Service.GetUserCountAsync();
            return Ok(queryResult.Result.ToUniHttpArrResponse(total: (int)countResult.Result));
        }


        [HttpGet]
        [Authorize]
        public async Task<ActionResult> QuerySelfProfile()
        {
            var userDocument = await Service.GetUserFromRequest(HttpContext.Request);
            if (!userDocument.IsSuccess) return Ok(userDocument.ToUniHttpResponse());
            var profileResult = await Service.GetProfile(userDocument.Result.id);
            return Ok(profileResult.ToUniHttpResponse());
        }


        [HttpPost]
        public async Task<ActionResult> QueryProfile(UniHttpRequest request)
        {
            var containsResult = request.Contains("value", "mode");
            if (!containsResult.IsSuccess) return Ok(containsResult.ToUniHttpResponse());
            request.TryGetValue("mode", out string mode, "ERROR");
            var pagingParam = request.ExtractPagingParams();
            var aggregation = new object().CreateOperationModeAggregation(mode.ToUserQueryMode(), pagingParam);
            var queryResult = await Service.GetProfile(aggregation);
            var countResult = await Service.GetUserCountAsync();
            return Ok(queryResult.Result.ToUniHttpArrResponse(total: (int)countResult.Result));
        }

        #endregion

        #region Modify

        //TODO:后续设为超管权限
        [HttpPost]
        [Authorize]
        [Authorize(Roles = "999")]
        public async Task<ActionResult> ModifyUserPass(UniHttpRequest request)
        {
            var containsResult = request.Contains("userId","newPass");
            if (!containsResult.IsSuccess) return Ok(containsResult.ToUniHttpResponse());
            request.TryGetValue("userId", out string userIdStr, "ERROR");
            request.TryGetValue("newPass", out string newPass, "123456");
            ObjectId.TryParse(userIdStr, out var userId);
            var updateResult = await Service.UpdateUserPassAsync(userId, newPass);
            return Ok(updateResult.ToUniHttpResponse());
        }


        [HttpPost]
        [Authorize]
        public async Task<ActionResult> ModifySelfPass(UniHttpRequest request)
        {
            var containsResult = request.Contains("oldPass", "newPass");
            if (!containsResult.IsSuccess) return Ok(containsResult.ToUniHttpResponse());
            var oldPassGetResult = request.TryGetValue("oldPass", out string oldPass, "123456");
            var newPassGetResult = request.TryGetValue("newPass", out string newPass, "123456");
            var userParseResult = await Service.GetUserFromRequest(HttpContext.Request);
            if (!userParseResult.IsSuccess) return Ok("".ToUniHttpResponse("User not found", 0));
            if(userParseResult.Result.Password != oldPass) return Ok("".ToUniHttpResponse("Old password is wrong", 0));
            var updateResult = await Service.UpdateUserPassAsync(userParseResult.Result.id, newPass);
            return Ok(updateResult.ToUniHttpResponse());
        }


        //TODO:后续为超管权限
        [HttpPost]
        [Authorize]
        [Authorize(Roles = "999")]
        public async Task<ActionResult> ModifyProfile(UniHttpRequest request)
        {
            var containsResult = request.Contains("userId");
            if (!containsResult.IsSuccess) return Ok(containsResult.ToUniHttpResponse());
            request.TryGetValue("userId", out string userIdStr, "ERROR");
            request.TryGetValue("nickName", out string? nickName);
            request.TryGetValue("phone", out string? phone);
            request.TryGetValue("avatarUrl", out string? avatarUrl);
            request.TryGetValue("department", out string? department);
            request.TryGetValue("responsibleProject", out string? responsibleProject);
            Dictionary<string, string?> updateDict = new Dictionary<string, string?>();
            updateDict.Add("nickName", nickName);
            updateDict.Add("phone", phone);
            updateDict.Add("avatarUrl", avatarUrl);
            updateDict.Add("department", department);
            updateDict.Add("responsibleProject", responsibleProject);
            ObjectId.TryParse(userIdStr, out var userId);
            var updateResult = await Service.UpdateProfile(userId,updateDict);
            return Ok(updateResult.ToUniHttpResponse());
        }


        [HttpPost]
        [Authorize]
        public async Task<ActionResult> ModifySelfProfile(UniHttpRequest request)
        {
            var userParseResult = await Service.GetUserFromRequest(HttpContext.Request);
            if (!userParseResult.IsSuccess) return Ok("".ToUniHttpResponse("User not found", 0));
            request.TryGetValue("nickName", out string? nickName);
            request.TryGetValue("phone", out string? phone);
            request.TryGetValue("avatarUrl", out string? avatarUrl);
            request.TryGetValue("department", out string? department);
            request.TryGetValue("responsibleProject",out string? responsibleProject);

            Dictionary<string, string?> updateDict = new Dictionary<string, string?>();
            updateDict.Add("nickName", nickName);
            updateDict.Add("phone", phone);
            updateDict.Add("avatarUrl", avatarUrl);
            updateDict.Add("department", department);
            updateDict.Add("responsibleProject", responsibleProject);

            var updateResult = await Service.UpdateProfile(userParseResult.Result.id, updateDict);
            return Ok(updateResult.ToUniHttpResponse());
        } 

        #endregion

        #region Delete

        //TODO:后续设为超管权限
        [HttpPost]
        [Authorize]
        [Authorize(Roles = "999")]
        public async Task<ActionResult> Delete(UniHttpRequest request)
        {
            var containsResult = request.Contains("userId");
            if (!containsResult.IsSuccess) return Ok(containsResult.ToUniHttpResponse());
            var userIdGetResult = request.TryGetValue("userId",out string userIdStr,"ERROR");
            try
            {
                ObjectId.TryParse(userIdStr, out ObjectId userId);
                var operationResult = await Service.RemoveUserAsync(userId);
                return Ok(operationResult.ToUniHttpResponse());
            }
            catch (Exception e)
            {
                return Ok("ERROR".ToUniHttpResponse(e.Message,0));
            }
        }

        #endregion

        #region Grant 认证


        [HttpPost]
        public async Task<ActionResult> Login(UniHttpRequest request)
        {
            var containsResult = request.Contains("username", "password");
            if (!containsResult.IsSuccess) return Ok(containsResult.ToUniHttpResponse());
            if (request.args == null) return Ok("No args provided".ToUniHttpResponse("Error", 0));
            var usernameGetResult = request.TryGetValue("username", out string username, "ERROR");
            var passwordGetResult = request.TryGetValue("password", out string password, "ERROR");
            if (!usernameGetResult.IsSuccess) return Ok(usernameGetResult.ToUniHttpResponse());
            if (!passwordGetResult.IsSuccess) return Ok(passwordGetResult.ToUniHttpResponse());
            var grantResult = await Service.GetJwtToken(new SUserDocument(username,password));

            return Ok(grantResult.ToUniHttpResponse());
        }


        [HttpGet]
        [Authorize]
        public async Task<ActionResult> VerifyLogin()
        {
            var userParseResult = await Service.GetUserFromRequest(HttpContext.Request);
            if (!userParseResult.IsSuccess) return Ok("".ToUniHttpResponse("User not found", 0));
            await Service.UpdateUserLastLoginTime(userParseResult.Result.id);
            return Ok(userParseResult.Message.ToUniHttpResponse());
        }

        #endregion

    }
}
